package org.example.sync.guarded;

/**
 * @author zhengdp
 * @Description
 * @Date 2022/10/16 22:07
 * @Created by zhengdp
 */
public class GuardedObject {
    /**
     * 结果对象
     */
    private Object response;

    // 获取结果
    public Object get(){
        synchronized (this){
            while(response == null){
                try{
                    this.wait();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
            return response;
        }
    }

    /**
     *  获取结果 - 增加最大等待时间
     * @param timeout 最大等待时间
     * @return 结果对象
     */
    public Object get(long timeout){
        synchronized (this){
            // 记录开始等待时间
            long begin = System.currentTimeMillis();
            long passTime = 0;
            while(response == null && passTime < timeout){
                try{
                    // 需要考虑 虚假唤醒的情况，当线程被虚假唤醒后，因为 response 仍然等于0，但是等待时间小于 timeout
                    // 所以还会进入 循环，但此时 wait的时间就不需要那么长了 ---> 保证总的等待时间 是 timeout
                    this.wait(timeout - passTime);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                // 判断经历时间是否超过了等待时间，如果超过，退出循环
                passTime = System.currentTimeMillis() - begin;
            }
            return response;
        }
    }

    // 产生结果
    public void complete(Object response){
        synchronized (this) {
            // 给结果成员变量赋值
            this.response = response;
            this.notifyAll();
        }
    }
}
